/*
 * Created on Feb 4, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.PropertyResourceBundle;

import javax.servlet.http.HttpServlet;

import org.apache.log4j.Logger;

import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.tdb.TDBFactory;
import com.hp.hpl.jena.util.FileManager;

import edu.mit.simile.longwell.corpus.Corpus;
import edu.mit.simile.longwell.schema.impl.LocalSchemaModel;
import edu.mit.simile.longwell.schema.impl.SchemaRegistry;

/**
 * @author dfhuynh
 */
public class LongwellServer {
	final static private Logger s_logger =
		Logger.getLogger(LongwellServer.class);
	private String sessionId;
	static private LongwellServer s_singleton = null;
	protected Profile	m_defaultProfile;
	protected Map		m_profiles = new HashMap();
	private static HashMap<String, String> usernames = new HashMap<String, String>();
	private static String mapKey;
	private static String applicationName;
	private static String fresnelPath;
	private static String graphsMappingPath;
	private static String version;
	private static String release;
	private static String serverUrl;
	private static String httpsPort;
	private static String proxyHost;
	private static String proxyPort;	
	private static String server_certificate;
	private static Model modelForAuthentication;
	private static String m_usersDatasetPath;
	private static int defaultFacetsNumber;
	private static int maxValueForFacet;
	private static String coordinateOnt;
	private static String useMap;
	private static String geocodingFile;
	final static public LongwellServer getServer() {
		return s_singleton;
	}
	
	public void setUserName(String idSession,String username){
		usernames.put(idSession, username);
	}
	public String getUserName(String idSession){
		return usernames.get(idSession);
	}
	
	public void removeUserName(String idSession){
		usernames.remove(idSession);
	}
	
	final static public String getMapKey() {
		return mapKey;
	}

	public void setMapKey(String key){
		mapKey=key;
	}
	final static public String getApplicationName() {
		return applicationName;
	}

	public void setApplicationName(String name){
		applicationName=name;
	}	
	final static public String getFresnelPath() {
		return fresnelPath;
	}

	public void setFresnelPath(String path){
		fresnelPath=path;
	}	
	
	final static public String getGraphsMappingPath() {
		return graphsMappingPath;
	}

	public void setGraphsMappingPath(String path){
		graphsMappingPath=path;
	}		
	
	
	/**
	 * @param defaultCorpus
	 * @param defaultCorpusSystemDir
	 * @param commonSystemDir
	 * @throws Exception
	 */
	public LongwellServer(
		Corpus	defaultCorpus,
		File	defaultCorpusSystemDir,
		File	commonSystemDir
	) throws Exception {
		s_logger.info("Creating Longwell server:\n" +
			"\tdefault corpus system dir: " + defaultCorpusSystemDir.getCanonicalPath() + "\n" +
			"\tcommon system dir:         " + commonSystemDir.getCanonicalPath());

		try {
			//if (s_singleton == null) {
				s_singleton = this;
				SchemaRegistry.startup(new File(commonSystemDir, "schema-registry"));
			//}

		//	m_defaultProfile = createDefaultProfile(
		//	m_defaultProfile = createProfile(id,
		//		defaultCorpus, defaultCorpusSystemDir);
		} catch (Exception e) {
			s_logger.error("Failed to construct Longwell server", e);
			throw e;
		}
	}

	/**
	 * Dispose the server and free up resources.
	 */
	synchronized public void dispose() {
		Iterator i = m_profiles.values().iterator();
		while (i.hasNext()) {
			((Profile) i.next()).dispose();
		}
		m_profiles.clear();

		if (m_defaultProfile != null) {
			m_defaultProfile.dispose();
			m_defaultProfile = null;
		}

		if (s_singleton == this) {
			SchemaRegistry.shutdown();
			s_singleton = null;
		}

		//Cache.printSummary();
	}
	synchronized public void dispose(String sessionId) {
		Profile prof = (Profile) m_profiles.get(sessionId);
		if(prof!=null){
			prof.disposeStructuredModels();
			prof.onBeforeRemove(prof.getModel());
			prof.getModel().removeAll();
			prof.onAfterRemove(prof.getModel());
			
			prof.getModel().close();
		}
		
		if(prof!=null){
			prof.dispose();
			prof=null;
		}
		
		m_profiles.remove(sessionId);
		/*
		if (s_singleton == this) {
			SchemaRegistry.shutdown();
			s_singleton = null;
		}
		*/
		//Cache.printSummary();
	}	

	/**
	 * Answer the default local profile.
	 *
	 * @return
	 */
	//synchronized public Profile getDefaultProfile() {
	//	return m_defaultProfile;
	//}

	/**
	 * Answer the profile with the given name
	 *
	 * @param name
	 * @return
	 */
	synchronized public Profile getProfile(String id) {
		/*
		if(m_defaultProfile!=null){
			if (m_defaultProfile.getID().equals(id)) {
				return getDefaultProfile();
			}

		} 
		if(m_defaultProfile.getID()!=id) {
			s_logger.info("LongwellServer: load profile from hash with id ---> "+id);
			return (Profile) m_profiles.get(id);
		}
		return m_defaultProfile;
		*/
		m_defaultProfile = (Profile) m_profiles.get(id);
		return (Profile) m_profiles.get(id);
	}

	protected Profile createDefaultProfile(
		Corpus	corpus,
		File	structuredModelsDir,
		PropertyResourceBundle languageBundle
	) {
		return new LocalProfile(
			"default",
			corpus,
			structuredModelsDir,
			languageBundle
		);
	}
	protected Profile createProfile(
			String sessionId,
			Corpus	corpus,
			File	structuredModelsDir,
			PropertyResourceBundle languageBundle
		) {
		Profile prof = new LocalProfile(
				sessionId,
				corpus,
				structuredModelsDir,
				languageBundle
			);
		addProfile(sessionId,prof);
		return prof;
		}	

	protected void addProfile(String id, Profile profile) {
		if(!m_profiles.containsKey(id))
			m_profiles.put(id, profile);
	}

	public void removeProfile(String id) {
		m_profiles.remove(id);
	}

	public void setVersion(String property) {
		version= property;
	}
	
	final static public String getVersion() {
		return version;
	}

	public void setServerURL(String url) {
		serverUrl= url;
	}
	
	final static public String getServerURL() {
		return serverUrl;
	}
	
	public void setHttpsPort(String port) {
		httpsPort= port;
	}
	
	final static public String getHttpsPort() {
		return httpsPort;
	}
	
	public void setRelease(String property) {
		release=property;	
	}
	final static public String getRelease() {
		return release;
	}
	public void setServerCertificate(String property) {
		server_certificate=property;	
	}
	final static public String getServerCertificate() {
		return server_certificate;
	}	
	public void setProxyHost(String host) {
		proxyHost=host;	
	}
	final static public String getProxyHost() {
		return proxyHost;
	}
	public void setProxyPort(String port) {
		proxyPort=port;	
	}
	final static public String getProxyPort() {
		return proxyPort;
	}	
	
	public void setUsersDatasetPath(String path) {
		m_usersDatasetPath=path;	
	}
	final static public String getUsersDatasetPath() {
		return m_usersDatasetPath;
	}	
	
	public void setModelForAuthentication(String path) {

		try {

			InputStream in = FileManager.get().open(path);
			if (in == null) {
				System.out.println("File: " + path
						+ " not found");

			}
			//modelForAuthentication = ModelFactory.createDefaultModel();
			//modelForAuthentication.read(in, null, "TURTLE");
			//modelForAuthentication = getBCCDataset().getDefaultModel();
			modelForAuthentication = getBCCDataset().getNamedModel("http://www.provincia.tn.it/bcc/resource/bcc-utenti");
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	final static public Model getModelForAuthentication(){
		return modelForAuthentication;
	}

	public void setDefaultFacetsNumber(int number) {
		defaultFacetsNumber=number;
		
	}
	final static public int getDefaultFacetsNumber(){
		return defaultFacetsNumber;
	}

	public void setMaxValueForFacet(int number) {
		maxValueForFacet=number;
		
	}
	final static public int getMaxValueForFacet(){
		return maxValueForFacet;
	}

	public void setCoordinateOnt(String coordOnt) {
		coordinateOnt=coordOnt; 
	}	
	
	public static String getCoordinateOnt(){
		return coordinateOnt;
	}
	
	public void setUseMap(String use){
		useMap=use;
	}
	
	public static String getUseMap(){
		return useMap;
	}
	public static Dataset getBCCDataset(){
		return 	TDBFactory.assembleDataset(LongwellServlet.getAssemblerDirectory()+"/bcc-utenti-assembler.ttl");
	}
	
	public void setGeocodingFile(String path){
		geocodingFile=path;
	} 
	
	public static String getGeocodingFile(){
		return geocodingFile;
	}
}
